package com.smart.community.gateway.filter;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.smart.community.gateway.utils.WebFluxSecurityUtils;

import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

/**
 * 网关认证过滤器
 * 负责Token验证和用户信息注入
 * 权限控制粒度简化：
 * - 移除细粒度权限验证逻辑
 * - 简化认证过滤器
 * - 保留Token验证和用户信息注入
 * 
 * @author Wu.Liang
 * @since 2025-07-02
 */
@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    @Autowired
    private WebClient.Builder webClientBuilder;
    
    // 不需要认证的路径 - 统一使用/api前缀
    private static final String[] WHITE_LIST = {
            "/actuator/**",
            "/api/user/auth/captcha",
            "/api/user/auth/check-login",
            "/api/user/auth/forgot-password",
            "/api/user/auth/login",
            "/api/user/auth/app/login",  // App端登录接口
            "/api/user/auth/phone-login",
            "/api/user/auth/refresh",    // 新增：refresh接口
            "/api/user/auth/refresh-token",
            "/api/user/auth/register", 
            "/api/user/auth/reset-password",
            "/api/user/auth/sms-code",
            "/api/user/auth/wechat-login",
            "/api/user/auth/wechat-qrcode",
            "/api/property/companies/register",
            "/doc.html",
            "/favicon.ico",
            "/health",
            "/swagger-resources/**",
            "/swagger-ui/**",
            "/v3/api-docs/**",
            "/webjars/**"
    };
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String requestURI = request.getURI().getPath();
        
        log.debug("简化AuthFilter处理请求: {}", requestURI);
        
        // 检查是否为白名单路径
        if (isWhitePath(requestURI)) {
            log.debug("请求路径在白名单中，跳过认证: {}", requestURI);
            return chain.filter(exchange);
        }
        
        // 获取Authorization header
        String authorization = request.getHeaders().getFirst("Authorization");
        
        if (StringUtils.hasText(authorization) && authorization.startsWith("Bearer ")) {
            try {
                log.debug("开始处理Token: {}", authorization);
                
                // 提取token（去掉"Bearer "前缀）
                String token = authorization.substring(7);
                
                // 验证token格式
                if (token.length() == 36 && token.matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}")) {
                    
                    // 调用用户服务验证Token并获取用户信息
                    return validateTokenAndGetUserInfo(token, exchange, chain);
                    
                } else if ("test-token".equals(token)) {
                    // 特殊处理测试Token，直接注入超级管理员信息
                    log.debug("检测到测试Token，注入超级管理员信息");
                    return injectTestUserInfo(token, exchange, chain);
                    
                } else {
                    log.warn("Token格式不正确: {}", token);
                    return unauthorized(exchange, "Token格式不正确");
                }
                
            } catch (Exception e) {
                log.error("Token处理异常: {}", e.getMessage(), e);
                return unauthorized(exchange, "Token处理失败: " + e.getMessage());
            }
        } else {
            log.warn("没有Bearer token或格式不正确");
            return unauthorized(exchange, "缺少有效的Authorization头");
        }
    }
    
    /**
     * 验证Token并获取用户信息
     */
    private Mono<Void> validateTokenAndGetUserInfo(String token, ServerWebExchange exchange, GatewayFilterChain chain) {
        return webClientBuilder.build()
                .post()
                .uri("http://smart-community-user/user/auth/verify-token")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .bodyValue("token=" + token)
                .retrieve()
                .bodyToMono(String.class)
                .flatMap(responseBody -> {
                    try {
                        Map<String, Object> response = objectMapper.readValue(responseBody, Map.class);
                        log.debug("用户服务Token验证响应: {}", response);
                        
                        // 检查响应状态
                        if (response == null || !"200".equals(String.valueOf(response.get("code")))) {
                            log.warn("Token验证失败: {}", response);
                            return unauthorized(exchange, "Token验证失败");
                        }
                        
                        // 获取用户信息
                        Map<String, Object> data = (Map<String, Object>) response.get("data");
                        if (data == null) {
                            log.warn("Token验证响应中无用户信息");
                            return unauthorized(exchange, "Token验证失败");
                        }
                        
                        // 构建用户信息对象
                        WebFluxSecurityUtils.GatewayUserInfo userInfo = new WebFluxSecurityUtils.GatewayUserInfo();
                        userInfo.setUserId(Long.valueOf(String.valueOf(data.get("userId"))));
                        userInfo.setUsername(String.valueOf(data.get("username")));
                        userInfo.setRealName(String.valueOf(data.get("realName")));
                        userInfo.setToken(token);
                        
                        // 直接使用用户服务返回的userType字符串，符合权威架构文档要求
                        userInfo.setUserType(String.valueOf(data.get("userType")));
                        userInfo.setSuperAdmin(Boolean.valueOf(String.valueOf(data.get("superAdmin"))));
                        
                        // 设置角色和权限
                        if (data.get("roles") != null) {
                            userInfo.setRoles((java.util.List<String>) data.get("roles"));
                        }
                        if (data.get("permissions") != null) {
                            userInfo.setPermissions((java.util.List<String>) data.get("permissions"));
                        }
                        
                        // 构建增强后的请求，注入用户信息到请求头
                        ServerHttpRequest.Builder requestBuilder = exchange.getRequest().mutate();
                        
                        // 保留原始的Authorization头
                        requestBuilder.header("Authorization", "Bearer " + token);
                        
                        // 注入用户信息到请求头
                        String[] userHeaders = WebFluxSecurityUtils.buildUserHeaders(userInfo);
                        for (int i = 0; i < userHeaders.length; i += 2) {
                            String headerName = userHeaders[i];
                            String headerValue = userHeaders[i + 1];
                            if (StringUtils.hasText(headerValue)) {
                                requestBuilder.header(headerName, headerValue);
                            }
                        }
                        
                        ServerHttpRequest enhancedRequest = requestBuilder.build();
                        ServerWebExchange enhancedExchange = exchange.mutate()
                                .request(enhancedRequest)
                                .build();
                        
                        // 详细的调试日志
                        log.debug("用户信息注入详情: userId={}, username={}, userType={}", 
                                userInfo.getUserId(), userInfo.getUsername(), userInfo.getUserType());
                        log.debug("注入的请求头: X-User-Id={}, X-User-Name={}, X-User-Type={}", 
                                enhancedRequest.getHeaders().getFirst("X-User-Id"),
                                enhancedRequest.getHeaders().getFirst("X-User-Name"),
                                enhancedRequest.getHeaders().getFirst("X-User-Type"));
                        log.debug("Token验证成功，用户信息: userId={}, username={}", 
                                userInfo.getUserId(), userInfo.getUsername());
                        
                        return chain.filter(enhancedExchange);
                        
                    } catch (Exception e) {
                        log.error("处理用户信息失败: {}", e.getMessage(), e);
                        return unauthorized(exchange, "处理用户信息失败");
                    }
                })
                .onErrorResume(e -> {
                    log.error("调用用户服务Token验证接口失败: {}", e.getMessage(), e);
                    return unauthorized(exchange, "Token验证服务不可用");
                });
    }
    
    /**
     * 注入测试用户信息（超级管理员）
     */
    private Mono<Void> injectTestUserInfo(String token, ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            // 构建测试用户信息对象
            WebFluxSecurityUtils.GatewayUserInfo userInfo = new WebFluxSecurityUtils.GatewayUserInfo();
            userInfo.setUserId(24L); // admin用户的ID
            userInfo.setUsername("admin");
            userInfo.setRealName("系统管理员");
            userInfo.setToken(token);
            userInfo.setUserType("SUPER_ADMIN");
            userInfo.setSuperAdmin(true);
            userInfo.setRoles(Arrays.asList("SUPER_ADMIN"));
            userInfo.setPermissions(Arrays.asList("*:*:*"));
            
            // 构建增强后的请求，注入用户信息到请求头
            ServerHttpRequest.Builder requestBuilder = exchange.getRequest().mutate();
            
            // 保留原始的Authorization头
            requestBuilder.header("Authorization", "Bearer " + token);
            
            // 注入用户信息到请求头
            String[] userHeaders = WebFluxSecurityUtils.buildUserHeaders(userInfo);
            for (int i = 0; i < userHeaders.length; i += 2) {
                String headerName = userHeaders[i];
                String headerValue = userHeaders[i + 1];
                if (StringUtils.hasText(headerValue)) {
                    requestBuilder.header(headerName, headerValue);
                }
            }
            
            ServerHttpRequest enhancedRequest = requestBuilder.build();
            ServerWebExchange enhancedExchange = exchange.mutate()
                    .request(enhancedRequest)
                    .build();
            
            log.debug("测试用户信息已注入到请求头，转发到下游服务");
            log.debug("测试Token验证成功，用户信息: userId={}, username={}", 
                    userInfo.getUserId(), userInfo.getUsername());
            
            return chain.filter(enhancedExchange);
            
        } catch (Exception e) {
            log.error("处理测试用户信息失败: {}", e.getMessage(), e);
            return unauthorized(exchange, "处理测试用户信息失败");
        }
    }

    /**
     * 检查是否为白名单路径
     */
    private boolean isWhitePath(String path) {
        for (String whitePath : WHITE_LIST) {
            if (whitePath.endsWith("/**")) {
                String prefix = whitePath.substring(0, whitePath.length() - 3);
                if (path.startsWith(prefix)) {
                    return true;
                }
            } else if (path.equals(whitePath) || path.startsWith(whitePath)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 返回未授权响应 - 标准JSON格式
     */
    private Mono<Void> unauthorized(ServerWebExchange exchange, String message) {
        ServerHttpResponse response = exchange.getResponse();
        
        try {
            // 构建标准JSON响应格式
            Map<String, Object> responseBody = new HashMap<>();
            responseBody.put("code", 401);
            responseBody.put("message", "未登录或登录已失效");
            responseBody.put("data", null);
            responseBody.put("success", false);
            responseBody.put("timestamp", System.currentTimeMillis());
            
            String jsonResponse = objectMapper.writeValueAsString(responseBody);
            DataBuffer buffer = response.bufferFactory().wrap(jsonResponse.getBytes(StandardCharsets.UTF_8));
            
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            
            log.warn("认证失败: {}", message);
            return response.writeWith(Mono.just(buffer));
            
        } catch (JsonProcessingException e) {
            log.error("JSON序列化失败", e);
            // 如果JSON序列化失败，返回简单的错误响应
            String fallbackResponse = "{\"code\":401,\"message\":\"未登录或登录已失效\",\"data\":null,\"success\":false}";
            DataBuffer buffer = response.bufferFactory().wrap(fallbackResponse.getBytes(StandardCharsets.UTF_8));
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.writeWith(Mono.just(buffer));
        }
    }
    
    @Override
    public int getOrder() {
        return -100; // 高优先级
    }
}
